package com.xjh.him.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xjh.him.common.LoginUser;
import com.xjh.him.dao.*;
import com.xjh.him.domain.*;
import com.xjh.him.dto.friendapply.FriendApplyDTO;
import com.xjh.him.dto.friendapply.FriendApplyInfoDTO;
import com.xjh.him.dto.friendapply.FriendHandleApplyDTO;
import com.xjh.him.netty.NettyCore;
import com.xjh.him.netty.codec.Command;
import com.xjh.him.netty.codec.Packet;
import com.xjh.him.netty.dto.FriendApplyNotifyDTO;
import com.xjh.him.netty.dto.UserSessionAddNotifyDTO;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xjh.tool.Checks;
import org.xjh.tool.common.ErrorMsg;
import org.xjh.tool.dto.PageResultDTO;
import org.xjh.tool.dto.ResultDTO;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FriendApplyServiceImpl implements IFriendApplyService {
    public static final String ACCEPT_GREET = "我通过了你的朋友申请，现在我们可以开始聊天了";

    @Autowired
    private FriendApplyMapper friendApplyMapper;

    @Autowired
    private FriendMapper friendMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private FriendGroupMapper friendGroupMapper;

    @Autowired
    private FriendGroupMsgMapper friendGroupMsgMapper;

    @Override
    public ResultDTO<Boolean> apply(FriendApplyInfoDTO applyInfoDTO) {
        if (Checks.isAnyEmpty(applyInfoDTO, applyInfoDTO.getAppliedId(), applyInfoDTO.getApplyInfo())) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_PARAMETER_IS_NULL);
        }
        UserDO loginUser = LoginUser.getLoginUser();
        UserDO userDO = userMapper.selectById(applyInfoDTO.getAppliedId());
        if (userDO == null) {
            return ResultDTO.getFailureResult("申请用户不存在");
        }

        QueryWrapper<FriendApplyDO> existQW = new QueryWrapper<>();
        existQW.eq("apply_user_id", loginUser.getId());
        existQW.eq("applied_user_id", applyInfoDTO.getAppliedId());
        existQW.eq("state", FriendApplyDO.STATE_APPLY);
        Integer count = friendApplyMapper.selectCount(existQW);
        if (count == 1) {
            return ResultDTO.getSuccessResult(true);
        }

        FriendApplyDO friendApplyDO = new FriendApplyDO();
        friendApplyDO.setApplyUserId(loginUser.getId());
        friendApplyDO.setApplyUserNickname(loginUser.getNickname());
        friendApplyDO.setApplyUserAvatar(loginUser.getAvatarUrl());
        friendApplyDO.setAppliedUserId(applyInfoDTO.getAppliedId());
        friendApplyDO.setAppliedUserNickname(userDO.getNickname());
        friendApplyDO.setAppliedUserAvatar(userDO.getAvatarUrl());
        friendApplyDO.setApplyInfo(applyInfoDTO.getApplyInfo());
        int insert = friendApplyMapper.insert(friendApplyDO);
        if (insert == 0) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_SYSTEM_BUSY);
        }

        //如果用户在线，则发送申请消息
        Channel channel = NettyCore.ACTIVE_USER_CHANNEL.get(applyInfoDTO.getAppliedId());
        if (channel != null) {
            channel.writeAndFlush(Packet.create(Command.FRIEND_APPLY_NOTIFY, new FriendApplyNotifyDTO()));
        }
        return ResultDTO.getSuccessResult(true);
    }

    @Transactional
    @Override
    public ResultDTO<Boolean> handleApply(FriendHandleApplyDTO handleApplyDTO) {
        if (Checks.isAnyEmpty(handleApplyDTO, handleApplyDTO.getId(), handleApplyDTO.getHandleState())) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_PARAMETER_IS_NULL);
        }
        Integer handle = friendApplyMapper.handleApply(handleApplyDTO.getId(), handleApplyDTO.getHandleState());
        if (handle == 0) {
            return ResultDTO.getFailureResult(ErrorMsg.ERR_SYSTEM_BUSY);
        }

        //如果同意申请
        if (FriendApplyDO.STATE_ACCEPT.equals(handleApplyDTO.getHandleState())) {
            //写好友表
            FriendApplyDO friendApplyDO = friendApplyMapper.selectById(handleApplyDTO.getId());
            FriendDO friendDO = new FriendDO();
            List<Long> idList = Arrays.asList(friendApplyDO.getApplyUserId(), friendApplyDO.getAppliedUserId());
            Collections.sort(idList);
            friendDO.setFirstId(idList.get(0));
            friendDO.setSecondId(idList.get(1));
            int insert = friendMapper.insert(friendDO);
            if (insert == 0) {
                throw new RuntimeException("insert friend failed");
            }

            //创建聊天组
            FriendGroupDO groupDO = new FriendGroupDO();
            groupDO.setFirstId(idList.get(0));
            groupDO.setSecondId(idList.get(1));
            int insertGroup = friendGroupMapper.insert(groupDO);
            if (insertGroup == 0) {
                throw new RuntimeException("insert friendGroup failed");
            }

            //创建开场白消息
            FriendGroupMsgDO applyUserMsgDO = new FriendGroupMsgDO();
            applyUserMsgDO.setFriendGroupId(groupDO.getId());
            applyUserMsgDO.setSenderId(friendApplyDO.getApplyUserId());
            applyUserMsgDO.setReceiverId(friendApplyDO.getAppliedUserId());
            applyUserMsgDO.setMsgType(FriendGroupMsgDO.MSG_TYPE_TEXT);
            applyUserMsgDO.setMsgContent(friendApplyDO.getApplyInfo());
            int insertApplyMsg = friendGroupMsgMapper.insert(applyUserMsgDO);
            if (insertApplyMsg == 0) {
                throw new RuntimeException("insertApplyMsg failed");
            }

            FriendGroupMsgDO appliedUserMsgDO = new FriendGroupMsgDO();
            appliedUserMsgDO.setFriendGroupId(groupDO.getId());
            appliedUserMsgDO.setSenderId(friendApplyDO.getAppliedUserId());
            appliedUserMsgDO.setReceiverId(friendApplyDO.getApplyUserId());
            appliedUserMsgDO.setMsgType(FriendGroupMsgDO.MSG_TYPE_TEXT);
            appliedUserMsgDO.setMsgContent(ACCEPT_GREET);
            int insertAppliedMsg = friendGroupMsgMapper.insert(appliedUserMsgDO);
            if (insertAppliedMsg == 0) {
                throw new RuntimeException("insertAppliedMsg failed");
            }

            //通知添加会话项
            Channel channel = NettyCore.ACTIVE_USER_CHANNEL.get(friendApplyDO.getApplyUserId());
            if (channel != null) {
                UserSessionAddNotifyDTO addNotifyDTO = new UserSessionAddNotifyDTO();
                addNotifyDTO.setTargetId(groupDO.getId());
                addNotifyDTO.setGroupType(UserSessionAddNotifyDTO.GROUP_TYPE_SINGLE);
                addNotifyDTO.setFriendId(friendApplyDO.getAppliedUserId());
                addNotifyDTO.setGroupName(friendApplyDO.getAppliedUserNickname());
                addNotifyDTO.setGroupAvatar(friendApplyDO.getAppliedUserAvatar());
                addNotifyDTO.setIsTop(false);
                addNotifyDTO.setNewestMsg(ACCEPT_GREET);
                channel.writeAndFlush(Packet.create(Command.USER_SESSION_ADD_NOTIFY, addNotifyDTO));
            }

            channel = NettyCore.ACTIVE_USER_CHANNEL.get(friendApplyDO.getAppliedUserId());
            if (channel != null) {
                UserSessionAddNotifyDTO addNotifyDTO = new UserSessionAddNotifyDTO();
                addNotifyDTO.setTargetId(groupDO.getId());
                addNotifyDTO.setGroupType(UserSessionAddNotifyDTO.GROUP_TYPE_SINGLE);
                addNotifyDTO.setFriendId(friendApplyDO.getApplyUserId());
                addNotifyDTO.setGroupName(friendApplyDO.getApplyUserNickname());
                addNotifyDTO.setGroupAvatar(friendApplyDO.getApplyUserAvatar());
                addNotifyDTO.setIsTop(false);
                addNotifyDTO.setNewestMsg(ACCEPT_GREET);
                channel.writeAndFlush(Packet.create(Command.USER_SESSION_ADD_NOTIFY, addNotifyDTO));
            }
        }
        return ResultDTO.getSuccessResult(true);
    }

    @Override
    public ResultDTO<Integer> countApply() {
        UserDO loginUser = LoginUser.getLoginUser();
        QueryWrapper<FriendApplyDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("applied_user_id", loginUser.getId());
        queryWrapper.eq("state", FriendApplyDO.STATE_APPLY);
        Integer count = friendApplyMapper.selectCount(queryWrapper);
        return ResultDTO.getSuccessResult(count);
    }

    @Override
    public PageResultDTO<FriendApplyDTO> listApply() {
        UserDO loginUser = LoginUser.getLoginUser();
        List<FriendApplyDO> applyDOList = friendApplyMapper.listApply(loginUser.getId());
        List<FriendApplyDTO> dtoList = applyDOList.stream().map(item -> {
            FriendApplyDTO applyDTO = new FriendApplyDTO();
            BeanUtils.copyProperties(item, applyDTO);
            return applyDTO;
        }).collect(Collectors.toList());
        PageResultDTO<FriendApplyDTO> pageResult = PageResultDTO.getSuccessPageResult(dtoList);
        pageResult.setTotal(dtoList.size());
        return pageResult;
    }
}
